/**
 * 
 */
package application;

import java.awt.Color;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.swing.JOptionPane;
import javax.swing.JTree;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeCellRenderer;
import javax.swing.tree.TreeNode;
import javax.swing.tree.TreePath;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.w3c.dom.Comment;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.w3c.dom.Text;
import org.xml.sax.SAXException;

@SuppressWarnings("serial")
public class XMLTree extends JTree {

	Document doc = null;
	File file = null;
	static public String path = "";
	DefaultTreeCellRenderer renderer;

	public XMLTree(final File file) throws IOException {
		this(new FileInputStream(file));
		this.setFile(file);

		renderer = (DefaultTreeCellRenderer) this.getCellRenderer();

	}

	public XMLTree(final InputStream in) {
		super(XMLTree.makeRootNode(in));
		final MouseListener ml = new MouseAdapter() {
			@Override
			public void mousePressed(final MouseEvent e) {
				final ArrayList<String> infoPath = new ArrayList<String>();
				if (e.getClickCount() == 1)
					
					renderer.setBackgroundSelectionColor(Color.WHITE);
				renderer.setTextSelectionColor(Color.GRAY);
				if (e.getClickCount() == 2) {
					path="";
					renderer.setBackgroundSelectionColor(Color.blue);
					renderer.setTextSelectionColor(Color.white);
					final TreePath selPath = XMLTree.this.getSelectionPath();					
					final DefaultMutableTreeNode selectedNode = (DefaultMutableTreeNode) selPath.getLastPathComponent();
					
				
					int i = 0;
					for (final TreeNode node : selectedNode.getPath()) {
						path += ">" + node.toString();
						if (i > 0) {
							infoPath.add(node.toString());
						}
						i++;
					}

					ApplicationEvents.setChecksFromTable();
					// JOptionPane.showMessageDialog(XMLTree.this.getParent(),
					// label);
					Document doc;
					try {
						doc = XMLTree.generateDocument(new FileInputStream(
								XMLTree.this.getFile()));
						
					final Element root = doc.getDocumentElement();
						
						
						Element element = null;
						for (final Object partOfPath : infoPath) {
							element = (Element) root.getElementsByTagName(
									partOfPath.toString()).item(0);
							
						}
//						 JOptionPane.showMessageDialog(XMLTree.this.getParent(),
//						 element.getTextContent());
					} catch (final FileNotFoundException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (final ParserConfigurationException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (final SAXException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					} catch (final IOException e1) {
						// TODO Auto-generated catch block
						e1.printStackTrace();
					}
				}
			}

		};
		this.addMouseListener(ml);

	}	
	private static DefaultMutableTreeNode makeRootNode(final InputStream in) {
		try {
			final Document document = XMLTree.generateDocument(in);
			document.getDocumentElement().normalize();
			final Element rootElement = document.getDocumentElement();
			final DefaultMutableTreeNode rootTreeNode = XMLTree.buildTree(rootElement);
			return rootTreeNode;
			
			
		} catch (final Exception e) {
			final String errorMessage = "Error making root node: " + e;
			System.err.println(errorMessage);
			e.printStackTrace();
			return new DefaultMutableTreeNode(errorMessage);
		}
	}

	private static DefaultMutableTreeNode buildTree(final Element rootElement) {
		final DefaultMutableTreeNode rootTreeNode = new DefaultMutableTreeNode(XMLTree.treeNodeLabel(rootElement));
		XMLTree.addChildren(rootTreeNode, rootElement);
		return rootTreeNode;
	}

	private static void addChildren(
			final DefaultMutableTreeNode parentTreeNode,
			final Node parentXMLElement) {
		final NodeList childElements = parentXMLElement.getChildNodes();
		for (int i = 0; i < childElements.getLength(); i++) {
			final Node childElement = childElements.item(i);
			if (!(childElement instanceof Text || childElement instanceof Comment)) {
				final DefaultMutableTreeNode childTreeNode = new DefaultMutableTreeNode(
						XMLTree.treeNodeLabel(childElement));
				parentTreeNode.add(childTreeNode);
				XMLTree.addChildren(childTreeNode, childElement);
			}
		}
	}

	private static String treeNodeLabel(final Node childElement) {
		final NamedNodeMap elementAttributes = childElement.getAttributes();
		final String treeNodeLabel = childElement.getNodeName();
		return treeNodeLabel;
	}

	private static String treeNodeLabelWithAttr(final Node childElement) {
		final NamedNodeMap elementAttributes = childElement.getAttributes();
		String treeNodeLabel = childElement.getNodeName();
		if (elementAttributes != null && elementAttributes.getLength() > 0) {
			treeNodeLabel = treeNodeLabel + " (";
			final int numAttributes = elementAttributes.getLength();
			for (int i = 0; i < numAttributes; i++) {
				final Node attribute = elementAttributes.item(i);
				if (i > 0) {
					treeNodeLabel = treeNodeLabel + ", ";
				}
				treeNodeLabel = treeNodeLabel + attribute.getNodeName() + "="
						+ attribute.getNodeValue();
			}
			treeNodeLabel = treeNodeLabel + ")";
		}
		return treeNodeLabel;
	}

	public Document getDoc() {
		return this.doc;
	}

	public void setDoc(final Document doc) {
		this.doc = doc;
	}

	public File getFile() {
		return this.file;
	}

	public void setFile(final File file) {
		this.file = file;
	}

	public static Document generateDocument(final InputStream in) throws ParserConfigurationException, SAXException, IOException {
		
		final DocumentBuilderFactory builderFactory = DocumentBuilderFactory.newInstance();
		final DocumentBuilder builder = builderFactory.newDocumentBuilder();
		return builder.parse(in);
	}
	
	
}
